package net.keebook.webapp.bean;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;

import net.keebook.webapp.dao.GroupDao;
import net.keebook.webapp.dao.KeeBookDao;
import net.keebook.webapp.dao.PasswordDao;
import net.keebook.webapp.dao.UserDao;
import net.keebook.webapp.entity.PasswordItem;
import net.keebook.webapp.entity.User;
import net.keebook.webapp.model.SessionModel;
import net.keebook.webapp.util.AccessRight;
import net.keebook.webapp.util.Messages;

import org.apache.log4j.Logger;


@ManagedBean
@RequestScoped
public class ListEntriesBean {
	@Inject
	private PasswordDao passwordDao;
	@Inject
	private GroupDao groupDao;
	@Inject
	private UserDao userDao;
	@Inject
	private KeeBookDao keeBookDao;
	private String searchKeyword;
	private SessionModel sessionModel;
	private List<PasswordItem> items = null;
	private String highlightId = "";
	
	@PostConstruct
	public void init() throws IOException {
		setSessionModel(SessionModel.getInstance(FacesContext.getCurrentInstance()));
		
		HttpServletRequest request = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
		String highlight = request.getParameter("highlight");
		if (highlight != null && !highlight.isEmpty()) {
			setHighlightId(highlight);
		}
		
		String searchKeyword = request.getParameter("s");
		if (searchKeyword != null && !searchKeyword.isEmpty()) {
			setSearchKeyword(searchKeyword);
		}
		
		String exposableId = request.getParameter("delete");
		if (exposableId != null && !"".equals(exposableId)) {
			if (!getKeeBookDao().getKeeBookAccess(getSessionModel(), AccessRight.READ_WRITE))  {
				Logger.getLogger(this.getClass()).warn("Forbidden access to bean from userId="+getSessionModel().getUserId());
				FacesContext.getCurrentInstance().getExternalContext().redirect("403.xhtml");
				return;
			}
			
			PasswordItem item = getPasswordDao().get(exposableId);
			if (item != null) {
				if (getPasswordDao().canAccess(getSessionModel().getUserId(), item.getId())) {
					getPasswordDao().delete(item);
					FacesContext.getCurrentInstance().getExternalContext().redirect("index.xhtml?msg="+Messages.ITEM_DELETED);
					return;
				}
			}
			FacesContext.getCurrentInstance().getExternalContext().redirect("index.xhtml?msg="+Messages.ITEM_DELETE_FAILED);
		}
	}
	
	public Boolean getRenderGroups() {
		User user = getUserDao().get(getSessionModel().getUserId());
		return user.getGroupItems();
	}
	
	public Boolean getHasGroups() {
		return getGroupDao().getHasGroups(getSessionModel().getUserId(), getSessionModel().getKeeBookId());
	}
	
	public List<PasswordItem> getItems() {
		if (items == null) {
			String highlight = getHighlightId();
			if (highlight == null || highlight.isEmpty()) {
				items = getPasswordDao().getList(getSessionModel().getUserId(), getSessionModel().getKeeBookId(), getSearchKeyword(), null, null);
			} else {
				items = new ArrayList<PasswordItem>();
				PasswordItem firstItem = getPasswordDao().get(highlight);
				if (firstItem != null) {
					items.add(firstItem);
				}
				items.addAll(getPasswordDao().getList(getSessionModel().getUserId(), getSessionModel().getKeeBookId(), getSearchKeyword(), null, highlight));
			}
			
			User user = getUserDao().get(getSessionModel().getUserId());
			if (user.getGroupItems()) {
				items = groupItems(items);
			}
		}
		return items;
	}
	
	private List<PasswordItem> groupItems(List<PasswordItem> ungrouped) {
		Map<String, List<PasswordItem>> grouped = new HashMap<String, List<PasswordItem>>();
		for (PasswordItem item : ungrouped) {
			String groupTitle = item.getGroup() == null ? "" : item.getGroup().getTitle();
			if (!grouped.containsKey(groupTitle)) {
				grouped.put(groupTitle, new ArrayList<PasswordItem>());
			}
			grouped.get(groupTitle).add(item);
		}
		
		List<String> sortedKeys = new ArrayList<String>(grouped.keySet());
		Collections.sort(sortedKeys, new Comparator<String>() {
			@Override
			public int compare(String o1, String o2) {
				return o1.toLowerCase().compareTo(o2.toLowerCase());
			}
		});
		
		List<PasswordItem> result = new ArrayList<PasswordItem>();
		for (String key : sortedKeys) {
			for (PasswordItem item : grouped.get(key)) {
				result.add(item);
			}
		}
		return result;
	}
	
	public void search() throws IOException {
		ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
		context.redirect("index.xhtml?s="+URLEncoder.encode(getSearchKeyword(), "UTF-8"));
	}
	
	public PasswordDao getPasswordDao() {
		return passwordDao;
	}

	public void setPasswordDao(PasswordDao passwordDao) {
		this.passwordDao = passwordDao;
	}

	public KeeBookDao getKeeBookDao() {
		return keeBookDao;
	}

	public void setKeeBookDao(KeeBookDao keeBookDao) {
		this.keeBookDao = keeBookDao;
	}

	public SessionModel getSessionModel() {
		return sessionModel;
	}

	public void setSessionModel(SessionModel sessionModel) {
		this.sessionModel = sessionModel;
	}

	public String getHighlightId() {
		return highlightId;
	}

	public void setHighlightId(String highlightId) {
		this.highlightId = highlightId;
	}

	public String getSearchKeyword() {
		return searchKeyword;
	}

	public void setSearchKeyword(String searchKeyword) {
		this.searchKeyword = searchKeyword;
	}

	public GroupDao getGroupDao() {
		return groupDao;
	}

	public void setGroupDao(GroupDao groupDao) {
		this.groupDao = groupDao;
	}

	public UserDao getUserDao() {
		return userDao;
	}

	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}
}
